package mebp.genetic.mutation;

import mebp.genetic.Individuum;
import mebp.genetic.Population;

import org.apache.log4j.Logger;

public class BreakAndRelinkMutation implements MutationStrategy{

	Logger log = Logger.getLogger(BreakAndRelinkMutation.class);
	private double probability;
	private Boolean keepBadMutations;
	
	public BreakAndRelinkMutation(double probability, Boolean keepBadMutations) {
		this.probability = probability;
		this.keepBadMutations = keepBadMutations;
	}
	
	// spaltet einen graphen an *einer* beliebigen stelle und setzt ihn dann neu zusammen
	public void mutate(Population population) {
		int next=(int)(Math.random()*population.getSize()*probability);
		for (Individuum i:population) {
			if (next-->0) continue;
			next=(int)(Math.random()*population.getSize()*probability);
			//if (Math.random()<probability) {
				
				Individuum iold = null;
				if (!keepBadMutations) {
					iold = (Individuum)i.clone();
				}
				// Mutate this
				i.optimize();

				int index = (int) (Math.random() * i.genom.length);
				if (i.genom[index] > 1) {
					i.genom[index]--;
					i.invalidateCache();
					i.repair();
				}
				if (!keepBadMutations) {
					double before=i.getFitness();
					double after = i.getFitness();
					// float improvement =
					// (Math.round((after/before-1)*10000)/100f)*-1;
					if (after < before) {
						log.trace("Mutation improved Fitness by "
							+ (Math.round((after / before - 1) * 10000) / 100f)
							* -1 + "%");
					} else {
						i = iold;
					}
				}
		}
	}
}
